package xfyun

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"time"
)

var (
	itr_apiUrl, _          = url.Parse("https://rest-api.xfyun.cn/v2/itr") // 请求地址
	itr_common             = &common{AppId: appid}
	itr_business           = &business{Ent: "math-arith", Aue: "raw"}
	itr_image_b64_max_size = 1024 * 1024 * 4
)

type itrRequestBody struct {
	Common   *common           `json:"common"`   // {"app_id":""}
	Business *business         `json:"business"` // {"ent": "math-arith", "aue": "raw"}
	Data     []byte            `json:"-"`
	DataMap  map[string]string `json:"data"` // {"image":"image_base64_str"}
}

func (b itrRequestBody) Marshal() []byte {
	j, _ := json.Marshal(b)
	return j
}

func (b *itrRequestBody) generateRequest() (req *http.Request, e error) {
	if len(b.Data) == 0 {
		return nil, ErrInvalidParams
	}
	if b.Common == nil {
		b.Common = itr_common
	}
	if b.Business == nil {
		b.Business = itr_business
	}
	if len(b.DataMap) == 0 {
		if b64str := b64(b.Data); len(b64str) > itr_image_b64_max_size {
			return nil, ErrXFFileSizeTooLarge
		} else {
			b.DataMap = map[string]string{"image": b64str}
		}
	}
	body := b.Marshal()
	req = &http.Request{
		Method: "POST",
		URL:    itr_apiUrl,
		Header: map[string][]string{},
		Body:   io.NopCloser(bytes.NewBuffer(body)),
	}
	b._assemblyRequestHeader(&req.Header, b.Data)
	return req, nil
}

// 文档：https://www.xfyun.cn/doc/words/photo-calculate-recg/API.html#%E6%8E%A5%E5%8F%A3%E8%B0%83%E7%94%A8%E6%B5%81%E7%A8%8B
func (b *itrRequestBody) _assemblyRequestHeader(header *http.Header, data []byte) {
	header.Set("Content-Type", "application/json")
	//设置请求头 其中Host Date 必须有
	header.Set("Host", itr_apiUrl.Host)
	//date必须是utc时区，且不能和服务器时间相差300s
	currentTime := time.Now().UTC().Format(time.RFC1123)
	header.Set("Date", currentTime)
	//对body进行sha256签名,生成digest头部，POST请求必须对body验证
	digest := "SHA-256=" + sha256B64(data)
	header.Set("Digest", digest)
	//根据请求头部内容，生成签名
	signature := b._generateSignatureOrigin(currentTime, "POST", digest)
	//组装Authorization头部
	authHeader := fmt.Sprintf(`api_key="%s", algorithm="hmac-sha256", headers="host date request-line digest", signature="%s"`, apikey, signature)
	header.Set("Authorization", authHeader)
}

func (b *itrRequestBody) _generateSignatureOrigin(date, httpMethod, digest string) string {
	signatureOrigin := fmt.Sprintf(`host: %s
date: %s
%s %s HTTP/1.1
digest: %s`, itr_apiUrl.Host, date, httpMethod, itr_apiUrl.RequestURI(), digest)
	hmacSignatureOrigin := hmacB64(signatureOrigin, []byte(secret))
	return hmacSignatureOrigin
}

type ItrResponseBody struct {
	Code    int                  `json:"code"`
	Message string               `json:"message"`
	Sid     string               `json:"sid"`
	Data    map[string]ItrResult `json:"data"`
}

type ItrResult struct {
	AttrException int              `json:"attr_exception"`
	Category      string           `json:"category"`        // 题型，当前只有"math_phfw_arith"
	MultiLineInfo ItrMultiLineInfo `json:"multi_line_info"` // 框选区域的小题
	RecogResult   []ItrRecogResult `json:"recog_result"`    // 当前题型所有小题的识别结果
	Version       string           `json:"version"`         // 接口版本
}

// 区域的小题
type ItrMultiLineInfo struct {
	ImpLineInfo []ItrLineInfo `json:"imp_line_info"` // 区域内所有小题/行
}

// 小题信息
type ItrLineInfo struct {
	LineRect     ItrLineRect `json:"imp_line_rect"` // 小题的坐标信息
	RecRejection int         `json:"rec_rejection"` // 可信度
	StrictScore  int         `json:"strict_score"`  // 预留字段，含义未知，无需关注
	TotalScore   int         `json:"total_score"`   // 此题判决。1-正确，0-错误
}

// 该行算式的坐标
type ItrLineRect struct {
	LeftUpPoint_x   int `json:"left_up_point_x"`    // 左上角X坐标
	LeftUpPoint_y   int `json:"left_up_point_y"`    // 左上角Y坐标
	RightDownPointX int `json:"right_down_point_x"` // 右下角X坐标
	RightDownPointY int `json:"right_down_point_y"` // 右下角Y坐标
}

// 区域的小题的识别结果
type ItrRecogResult struct {
	LineCharResult interface{}         `json:"line_char_result"` // 预留字段，含义未知，无需关注
	LineWordResult []ItrLineWordResult `json:"line_word_result"` // 小题识别结果
}

// 小题识别结果
type ItrLineWordResult struct {
	BegPos      []int     `json:"beg_pos"`
	BegPosX     []int     `json:"beg_pos_x"`
	BegPosY     []int     `json:"beg_pos_y"`
	EndPos      []int     `json:"end_pos"`
	EndPosX     []int     `json:"end_pos_x"`
	EndPosY     []int     `json:"end_pos_y"`
	WordContent []string  `json:"word_content"` // 文字识别结果
	WordGwpp    []float64 `json:"word_gwpp"`    // 文字的后验概率
}
